#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <time.h>
#include <limits.h>
#include <unistd.h>


#define PORT1 7655
#define PORT2 7656
#define BSIZE 1024
#define SEQLENGTH 8		//sequence number length in bytes
#define IDLENGTH 1
#define RLIMIT 100
#define SIZELENGTH 2

long timestamp() {
	time_t ltime;
	struct timeval ts;
	long timeinms;
	ltime = time(NULL);
	gettimeofday(&ts, NULL);
	timeinms = ts.tv_sec * 1000000 + ts.tv_usec;
	//printf("Here is the time in time from tstamp in microsec: %ld\n", timeinms);
	return timeinms;
}

long gettimefrompacket(char* buffer) {
	long temp = atol(buffer + IDLENGTH + SEQLENGTH + SIZELENGTH);
	//printf("Here is the time from recv in time in microsec: %ld\n", temp);
	return temp;
}

int getseqfrompacket(char* buffer) {
	char temp[SEQLENGTH];
//	printf("here is ur buffer from packet: %s\n", buffer);
	strncpy(temp, buffer + IDLENGTH + SIZELENGTH, SEQLENGTH);
//	printf("here is ur seq from packet: %d\n", atoi(temp));
	return atoi(temp);
}

int main(int argc, char *argv[]) {
	int sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
	int maxt, mint, success, seqnum, i, PORTF, PORT, FLAG1, FLAG2;
	long delayarray[RLIMIT];
	long sendtime, rectime;
	struct sockaddr_in sa;
	char buffer[BSIZE];
	size_t fromlen, recsize;

	if (argc != 4) {
		printf("argc: %d\n", argc);
		printf("Format: dest id flag1 flag2;(id:1 for client1, 2 for client 2; flag1 set to output seccess, flag 2 set to output Trec-Tsent)\n");
		exit(EXIT_FAILURE);
	}
	//we assume no invalid input
	PORTF = atoi(argv[1]);
	if (PORTF==1)
		PORT = PORT1;
	if (PORTF==2)
		PORT = PORT2;
	FLAG1 = atoi(argv[2]);
	FLAG2 = atoi(argv[3]);

	seqnum = 0;
	success = 0;
	maxt = INT32_MIN;
	mint = INT32_MAX;

	memset(&sa, 0, sizeof(sa));
	sa.sin_family = AF_INET;
	sa.sin_addr.s_addr = INADDR_ANY;
	sa.sin_port = htons(PORT);

	if (-1 == bind(sock, (struct sockaddr *) &sa, sizeof(struct sockaddr))) {
		perror("error bind failed");
		close(sock);
		exit(EXIT_FAILURE);
	}

	//printf("Destination Starts...\n");
	while (success < RLIMIT) {
		//printf("recv test....success recieved: %d\n", success);
		recsize = recvfrom(sock, (void *) buffer, 1024, 0,
				(struct sockaddr *) &sa, &fromlen);

		if (recsize > 0) {
//			printf("here is the buffer %s\n", buffer);
			success++;
			if (FLAG2) {
				rectime = timestamp();
				sendtime = gettimefrompacket(buffer);
				//printf("MaxtD is at %ld\t%ld", rectime, sendtime);
				delayarray[success] = rectime - sendtime;
			}
			//printf("recsize: %d\n ", recsize);
			//printf("Successes: %d\n", success);
		}
	}

	close(sock); /* close the socket */

	if (FLAG1)
		printf("%f\n",
				((float) RLIMIT / (float) (getseqfrompacket(buffer) + 1)));//success
	if (FLAG2) {
		for (i = 0; i < RLIMIT; i++) {
			printf("%d\n", delayarray[i]);//Tsent-Trec
		}
		printf("END\n");
	}

	return 0;
}
